SpringBoot Elasticsearch 7.x 多条件分页查询

您所在的位置:网站首页 elasticsearchrepository 更新 SpringBoot Elasticsearch 7.x 多条件分页查询

SpringBoot Elasticsearch 7.x 多条件分页查询

2024-07-04 20:26| 来源: 网络整理| 查看: 265

本文目的记录下新版本的Elasticsearch API查询使用

目录 why elasticsearchconcepthow use elasticsearch版本说明安装说明创建索引和映射新建Repository新建 service接口和实现类POJO 封装对象测试

why elasticsearch

Elasticsearch 不多说了:

用途广泛,社区活跃,Apache开源许可免费分布式多用户能力的全文搜索引擎可RESTful web接口,可多语言API接口它是用Java语言开发的企业级搜索引擎

我这里主要用作全文搜索引擎,市面上也有不少其他的简单易用的搜索引擎,不过考虑社区活跃程度,大众认知程度最终还是选择elasticsearch ,主要它的组合ELK可以作为分布式日志管理工具。

concept Elasticsearch很多概念与MySQL类似的,对比关系: ESMysql索引库(indices)Databases 数据库类型(type)Table 数据表文档(Document)Databases 数据库字段(Field)Column 列

Es的映射配置(mappings) 指设置字段的数据类型、属性、是否索引、是否存储等特性。

集群相关的概念: 索引集(Indices,index的复数):逻辑上的完整索引 分片(shard):数据拆分后的各个部分 副本(replica):每个分片的复制

分布式说明 Es本身分布式,即便你只有一个节点,默认也会对你的数据进行分片和副本操作, 当你向集群添加新数据时,数据也会在新加入的节点中进行平衡(负载均衡)。

how use elasticsearch 版本说明

软件环境: JDK1.8 SpringBoot 2.3.8

org.springframework.boot spring-boot-starter-parent 2.3.8.RELEASE

ES, 这里和SpringBoot 对应的默认版本是 7.6.2

org.springframework.boot spring-boot-starter-data-elasticsearch

springboot yml 文件配置说明:

spring: elasticsearch: rest: uris: http://你的es服务器地址:9200 安装说明

ES 的安装步骤省略…网上一搜一大把,这里是docker单机版本的

docker run -p 9200:9200 -p 9300:9300 -d --name=es -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" -e "discovery.type=single-node" elasticsearch:7.11.2

这里重点说一下中文分词: ElasticSearch 默认采用分词器, 单个字分词 ,效果很差。

下面是es中文分词库,与Elasticsearch一起维护升级,版本也保持一致 https://github.com/medcl/elasticsearch-analysis-ik/releases

下载 zip压缩文件,直接解压到 elasticsearch/plugins 目录下新建一个文件夹名称为 ik 在这里插入图片描述 进入config目录,修改一下 IKAnalyzer.cfg.xml 将扩展的分词库加入进去,然后重启es即可,不然像停顿词 “的地得” 还是会做倒排索引的 在这里插入图片描述

创建索引和映射

这里说一下es7.x 相对于 6.x ,很多api过时了,需要使用新的。

这里测试创建一个索引叫“documentlibrary” ,存放各类文档。

重点说明:

如果是单机版本的一台服务器上的 es,那么 创建的index中 replicas 必须为0, 因为es的分片副本不可和原分片在同一个节点上(即同一台服务或同一个虚拟操作系统中) import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; import java.io.Serializable; /** * 针对文档库中的文档存储在 es中的对象信息 * * @author admin */ @Document(indexName = "documentlibrary", shards = 2, replicas = 0) @Data public class DocumentLibrary implements Serializable { private static final long serialVersionUID = 1L; /** * 主键 */ @ApiModelProperty(value = "主键") @Id private Long id; /** * t_oss_upload_record 表id */ @ApiModelProperty(value = "t_oss_upload_record 表id") @Field(name = "ossUploadRecord", type = FieldType.Long) private Long ossUploadRecord; /** * 文件分类 */ @ApiModelProperty(value = "文件分类") @Field(name = "categories", type = FieldType.Keyword) private String categories; /** * 原始文件名称 */ @ApiModelProperty(value = "原始文件名称") @Field(name = "originalFileName", type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart") private String originalFileName; /** * 上传服务器的最终地址 */ @ApiModelProperty(value = "上传服务器的最终地址") @Field(name = "resultPath", type = FieldType.Keyword) private String resultPath; /** * 摘要 */ @ApiModelProperty(value = "摘要") @Field(name = "summary", type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart") private String summary; /** * 整体内容抽取 */ @ApiModelProperty(value = "【一般不展示该字段,只存储使用】整体内容抽取") @Field(name = "allContent", type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart") private String allContent; /** * 版本 */ @ApiModelProperty(value = "版本") @Field(name = "rversion", type = FieldType.Keyword) private String rversion; /** * 创建人 */ @ApiModelProperty(value = "创建人") @Field(name = "createUser", type = FieldType.Keyword) private String createUser; /** * 创建日期 */ @ApiModelProperty(value = "创建日期") @Field(name = "createTime", type = FieldType.Text, fielddata = true) private String createTime; /** * 文件类型后缀 */ @ApiModelProperty(value = "文件类型后缀") @Field(name = "fileType", type = FieldType.Keyword) private String fileType; /** * 关键字1 */ @ApiModelProperty("关键字1") @Field(name = "Keyword1", type = FieldType.Keyword) private String Keyword1; /** * 关键字1 */ @ApiModelProperty("关键字2") @Field(name = "Keyword2", type = FieldType.Keyword) private String Keyword2; /** * 关键字1 */ @ApiModelProperty("关键字1") @Field(name = "Keyword3", type = FieldType.Keyword) private String Keyword3; /** * 关键字4 */ @ApiModelProperty("关键字4") @Field(name = "Keyword4", type = FieldType.Keyword) private String Keyword4; /** * 关键字5 */ @ApiModelProperty("关键字5") @Field(name = "Keyword5", type = FieldType.Keyword) private String Keyword5; } 新建Repository import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; /** * 针对文档库中的文档存储在 es中的对象信息 * * @author guzt */ public interface DocumentLibraryRepository extends ElasticsearchRepository { } 新建 service接口和实现类 import com.middol.colburn.oss.model.client.es.DocumentLibrary; import com.middol.colburn.oss.model.client.pojo.query.DocumentLibraryQuery; import com.middol.starter.common.pojo.vo.PageVO; /** * ES 服务类 * * @author admin */ public interface DocumentLibraryService { /** * 保存一条数据类型 * * @param entity DocumentLibrary */ void save(DocumentLibrary entity); /** * 详细条件全文检索 * * @param query DocumentLibraryQuery * @return PageInfo */ PageVO search(DocumentLibraryQuery query); }

下面的search 实现的查询功能如下: 如果传递了 keywordFilterTxt 参数则做全文所有字段检索,如果传递其他字段则另外还进行过滤操作

addFields 指的是查询出哪些字段StrUtil 是hutools里面的工具类init 是初始化创建索引和映射 import cn.hutool.core.util.StrUtil; import com.middol.colburn.oss.model.client.es.DocumentLibraryRepository; import com.middol.colburn.oss.model.client.es.DocumentLibrary; import com.middol.colburn.oss.model.client.pojo.query.DocumentLibraryQuery; import com.middol.colburn.oss.model.client.service.DocumentLibraryService; import com.middol.starter.common.pojo.vo.PageVO; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.sort.SortBuilders; import org.elasticsearch.search.sort.SortOrder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.data.domain.PageRequest; import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; import org.springframework.data.elasticsearch.core.IndexOperations; import org.springframework.data.elasticsearch.core.SearchHit; import org.springframework.data.elasticsearch.core.SearchHits; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import java.util.List; import java.util.stream.Collectors; /** * ES 服务类 * * @author admin */ @Service("documentLibraryServiceImpl") @ConditionalOnClass({ElasticsearchRestTemplate.class}) public class DocumentLibraryServiceImpl implements DocumentLibraryService { protected Logger logger = LoggerFactory.getLogger(this.getClass()); final ElasticsearchRestTemplate elasticsearchRestTemplate; final DocumentLibraryRepository documentLibraryRepository; public DocumentLibraryServiceImpl(ElasticsearchRestTemplate elasticsearchRestTemplate, DocumentLibraryRepository documentLibraryRepository) { this.elasticsearchRestTemplate = elasticsearchRestTemplate; this.documentLibraryRepository = documentLibraryRepository; } @PostConstruct public void init() { IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(DocumentLibrary.class); if (!indexOperations.exists()) { // 创建索引,会根据Item类的@Document注解信息来创建 boolean result = indexOperations.create(); logger.info("创建 elasticsearch 索引 DocumentLibrary, 创建结果={}", result); if (!result) { throw new RuntimeException("创建 elasticsearch 索引失败"); } else { // 配置映射,会根据Item类中的id、Field等字段来自动完成映射 indexOperations.createMapping(); } } } @Override public void save(DocumentLibrary entity) { elasticsearchRestTemplate.save(entity); } @Override public PageVO search(DocumentLibraryQuery query) { PageVO pageVO = new PageVO(); if (query.getPageNum() == null || query.getPageNum().equals(0)) { query.setPageNum(1); } if (query.getPageSize() == null || query.getPageSize().equals(0)) { query.setPageNum(10); } // 构建查询条件 NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); BoolQueryBuilder filter = QueryBuilders.boolQuery(); // 添加基本分词查询 if (StrUtil.isNotBlank(query.getCategories())) { filter.must(QueryBuilders.termQuery("categories", query.getCategories())); } if (StrUtil.isNotBlank(query.getFileType())) { filter.must(QueryBuilders.termQuery("fileType", query.getFileType())); } if (StrUtil.isNotBlank(query.getOriginalFileName())) { filter.must(QueryBuilders.matchQuery("originalFileName", query.getOriginalFileName())); } if (StrUtil.isNotBlank(query.getRversion())) { filter.must(QueryBuilders.termQuery("rversion", query.getRversion())); } if (StrUtil.isNotBlank(query.getCreateBeginTime())) { filter.must(QueryBuilders.rangeQuery("createTime").gte(query.getCreateBeginTime() + " 00:00:00")); } if (StrUtil.isNotBlank(query.getCreateEndTime())) { filter.must(QueryBuilders.rangeQuery("createTime").lte(query.getCreateBeginTime() + " 23:59:59")); } if (StrUtil.isNotBlank(query.getKeywordFilterTxt())) { queryBuilder.withQuery(QueryBuilders.queryStringQuery(query.getKeywordFilterTxt())); } queryBuilder.withFilter(filter); queryBuilder.withSort(SortBuilders.fieldSort("id").order(SortOrder.DESC)); queryBuilder.withPageable(PageRequest.of(query.getPageNum() - 1, query.getPageSize())); NativeSearchQuery nativeSearchQuery = queryBuilder.build(); nativeSearchQuery.addFields("id", "ossUploadRecord", "categories","originalFileName", "resultPath","summary","rversion","createUser","createTime","fileType", "Keyword1","Keyword2","Keyword3","Keyword4","Keyword5","Keyword6","Keyword7","Keyword8"); // 使用ElasticsearchRestTemplate进行复杂查询 SearchHits searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, DocumentLibrary.class); if (searchHits.getTotalHits() > 0) { List searchProductList = searchHits.stream().map(SearchHit::getContent).collect(Collectors.toList()); pageVO.setPageNum(query.getPageNum()); pageVO.setPageSize(query.getPageSize()); pageVO.setRows(searchProductList); pageVO.setTotal(searchHits.getTotalHits()); pageVO.setPages((int) Math.ceil((double) pageVO.getTotal() / query.getPageSize())); } return pageVO; } } POJO 封装对象

这里的 POJO,query 和 pageVO 代码如下:

import io.swagger.annotations.ApiModelProperty; import java.util.List; /** * 数据库分页查询列表封装对象 * * @param 实体类对象 * @author admin */ @Data public class PageVO implements Serializable { private static final long serialVersionUID = 1L; /** * 总记录数 */ @ApiModelProperty(value = "总记录数") private Long total; /** * 当前页 */ @ApiModelProperty(value = "当前页") private Integer pageNum; /** * 每页的数量 */ @ApiModelProperty(value = "每页的数量") private Integer pageSize; /** * 结果集 */ @ApiModelProperty(value = "结果集") private List rows; /** * 总页数 */ @ApiModelProperty(value = "总页数") private Integer pages; } import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; /** * 文件上传记录(OssUploadRecord)表查询条件封装对象 * * @author admin */ @Data public class DocumentLibraryQuery implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty("当前页码,从1开始") private Integer pageNum = 1; @ApiModelProperty("每页大小,默认10") private Integer pageSize = 10; @ApiModelProperty(value = "文件分类") private String categories; @ApiModelProperty(value = "文件名称全文检索") private String originalFileName; @ApiModelProperty(value = "关键字全文检索") private String keywordFilterTxt; @ApiModelProperty(value = "版本") private String rversion; @ApiModelProperty(value = "创建日期 yyyy-mm-dd") private String createBeginTime; @ApiModelProperty(value = "结束日期 yyyy-mm-dd") private String createEndTime; @ApiModelProperty(value = "文件类型后缀") private String fileType; } 测试

我这里写了一个controller方法:

@ApiOperation(value = "测试ES", notes = "通过pagehelper插件进行物理分页") @ApiImplicitParam(name = "query", value = "前端参数封装", dataType = "DocumentLibraryQuery") @PostMapping(value = "testEs") public ResponseVO testEs(@RequestBody @Validated DocumentLibraryQuery query) { return ResponseVO.success(documentLibraryService.search(query)); }

在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3